package lerFormatos;

import grafoS.Graph;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

/**
 * Gcol is a program to help users to learn a little about graph coloring, in
 * this software, you can learn some coloring algorithms, and add your own
 * algorithm for coloring.You can also learn BFS and DFS search. This tool, also
 * support the .col format from DIMACS (Center for Discrete Mathematics and
 * Theoretical Computer Science), so you can import a big graph and use all the
 * algorithms. Copyright (C) <2015> Clóvis Daniel Souza Silva, Samuel Silva de
 * Souza, Professor Leonardo Sampaio Rocha.
 * 
* This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
* This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
* You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 * contact: projetoGrafos@gmail.com
 */
/**
 *
 * @author Daniel
 * @author Samuel
 */
/**
 *
 * In this class, we'll read a DIMACS(.col) file.
 */
public class LerArquivo {

    private Graph g;

    /**
     * This it's the static method which we use in the interface, to read the
     * DIMACS(.col) file.
     *
     * @param f receives the file.
     * @return return the graph.
     */
    public static Graph lerDIMACS(File f) {
        int i = read('p', null, f)[0];
        Graph G = new Graph(i);
        read('e', G, f);

        return G;
    }

    /**
     * Here we'll start to read the file as a simple txt to create a graph,
     * we'll read line by line.
     *
     * @param func define if we'll read to create a graph, or to link the vertex
     * of a created graph. In a .col file, 'p' represents the line where it says
     * the total of vertices and edges. 'e', in the same file, represents a link
     * betwen two vertices.
     * @param G Receives a graph to modify.
     * @param file Receives the file.
     * @return We'll got a vector with lenght two, when we use 'p' as char
     * parameter we'll just use the first of this vector(the total of vertex),
     * in the second slot we'll have the total of edges. when we use 'e' as char
     * parameter, we got the first vertex on the first slot, and the second
     * vertex on the second slot.
     */
    public static int[] read(char func, Graph G, File file) {

        int[] ver = new int[2];
        try {
            FileReader arq = new FileReader(file);
            BufferedReader lerArq = new BufferedReader(arq);

            String linha = lerArq.readLine();
            while (linha != null) {
                //System.out.printf("%s\n", linha);
                if (ver[0] == 0 && func == 'p') {
                    ver = lerFuncao(linha, func);
                } else if (func == 'e' && G != null) {
                    ver = lerFuncao(linha, func);
                    G.aresta(ver[0], ver[1], false);
                }
                linha = lerArq.readLine();

            }

            arq.close();
        } catch (IOException e) {
            System.err.printf("Erro na abertura do arquivo:  %s \n", e.getMessage());
        }
        return ver;

    }

    /**
     * We'll recive the line here, and then we'll define what this line
     * represents(a edge, or the creation of a graph), then we'll convert the
     * string in two integers. It's important to read the methods used in this
     * one.
     *
     * @param s A line of the file.
     * @param func 'e' or 'p'
     * @return A vector with two integers.
     */
    private static int[] lerFuncao(String s, char func) {
        int[] ver = new int[2];// vetor com os 2 vertices;
        int[] num = new int[17];
        int index = 0;
        for (int i = 0; i < num.length; i++) {
            num[i] = -1;
        }
        if (s.charAt(0) == func) {
            for (int i = 0; i < s.length(); i++) {
                if ((s.charAt(i) >= '0') && (s.charAt(i) <= '9')) {
                    num[index] = s.charAt(i) - 48;
                    index++;
                } else {
                    index++;
                }

            }
            //System.out.println();
            ver = tamanhoDaEntrada(num);

        } else {
            System.out.printf("");
        }

        return ver;

    }

    /**
     * Here we already converted the line in a vector of integers, now we'll
     * split in two integers.
     *
     * @param vet A vector of integers with one digit.
     * @return A vector with two integers
     */
    private static int[] tamanhoDaEntrada(int[] vet) {
        int[] entrada = new int[2];
        int index = 0;
        int aux = 0;
        for (int i = 0; i < vet.length; i++) {
            if (vet[i] != -1) {
                aux = i;
                break;
            }
        }
        for (int i = aux; i < vet.length; i++) // (The two first elements are -1, because they represent 'e'/'p' and ' '
        //  of the line) Here, we're cheking the size of each int.
        {
            if (vet[i] != -1) {
                entrada[index]++;
            } else {
                index++;
            }
            if (index > 1) {
                break;
            }
        }
        int[] vet1 = new int[entrada[0]];
        int[] vet2 = new int[entrada[1]];
        int flag = 0;
        index = 0;
        for (int i = aux; i < vet.length; i++) {
            if (vet[i] == -1 && flag == 1) {
                break;
            }
            if (vet[i] != -1 && flag == 1) {
                vet2[index] = vet[i];
                index++;
            }
            if (vet[i] != -1 && flag == 0) {
                vet1[index] = vet[i];
                index++;
            }
            if (vet[i] == -1) {
                flag = 1;
                index = 0;
            }
        }
        return converterParaInteiro(entrada, vet1, vet2);
    }

    /**
     * Finally we'll convert the two vector of integers which represents two
     * integers, into two integers.
     *
     * @param ent The size of the integer
     * @param vet1 The vector with the firts integer.
     * @param vet2 The vector with the second integer.
     * @return the vector with two integers.
     */
    private static int[] converterParaInteiro(int[] ent, int[] vet1, int[] vet2) {
        int num1 = 0, num2 = 0;
        int[] num = new int[2];

        for (int i = 0; i < vet1.length; i++) {
            vet1[i] = (int) (vet1[i] * Math.pow(10, ent[0] - 1));
            ent[0]--;
            num1 += vet1[i];
        }
        for (int i = 0; i < vet2.length; i++) {
            vet2[i] = (int) (vet2[i] * Math.pow(10, ent[1] - 1));
            ent[1]--;
            num2 += vet2[i];
        }
        //System.out.printf("%d. %d. \n", num1,num2);
        num[0] = num1;
        num[1] = num2;
        return num;
    }
}
